﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using LayeredArchitectureSample.Infrastructure;
using LayeredArchitectureSample.Infrastructure.Services;
using LayeredArchitectureSample.ServiceContracts;

namespace LayeredArchitectureSample.ViewModel
{
    internal class LocationsViewModel : INotifyPropertyChanged
    {
        private readonly IServiceOperationInvoker<IRemoteLocationRepository> _remoteLocationRepository;

        private readonly ObservableCollection<LocationViewModel> _locations;
        private LocationViewModel _currentlySelectedLocation;
        private bool _isSomethingSelected;
        private readonly IApplicationController _applicationController;
        private readonly string _isSomethingSelectedPropertyName;
        private readonly string _selectedItemPropertyName;
        private readonly IExceptionAwareServiceCodeRunner _codeRunner;

        public LocationsViewModel(
            IEnumerable<LocationViewModel> locations,
            IServiceOperationInvoker<IRemoteLocationRepository> remoteLocationRepository,
            IApplicationController applicationController,
            IExceptionAwareServiceCodeRunner codeRunner)
        {
            if (locations == null) throw new ArgumentNullException("locations");
            if (remoteLocationRepository == null) throw new ArgumentNullException("remoteLocationRepository");
            if (applicationController == null) throw new ArgumentNullException("applicationController");
            if (codeRunner == null) throw new ArgumentNullException("codeRunner");

            _remoteLocationRepository = remoteLocationRepository;
            _codeRunner = codeRunner;
            _applicationController = applicationController;
            _locations = new ObservableCollection<LocationViewModel>(locations);

            _isSomethingSelectedPropertyName = Reflection.GetPropertyName(
                    () => this.IsSomethingSelected);

            _selectedItemPropertyName = Reflection.GetPropertyName(() => this.CurrentlySelectedLocation);
        }

        public ObservableCollection<LocationViewModel> Locations
        {
            get { return _locations; }
        }

        public LocationViewModel CurrentlySelectedLocation
        {
            get { return _currentlySelectedLocation; }
            set
            {
                _currentlySelectedLocation = value;

                this.IsSomethingSelected = (_currentlySelectedLocation != null);

                EventRaiser.RaisePropertyChangedEvent(PropertyChanged, this,
                    _selectedItemPropertyName);
            }
        }

        public bool IsSomethingSelected
        {
            get
            {
                return _isSomethingSelected;
            }
            set
            {
                _isSomethingSelected = value;

                EventRaiser.RaisePropertyChangedEvent(PropertyChanged, this,
                                                      _isSomethingSelectedPropertyName);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void RemoveSelectedLocation()
        {
            _codeRunner.RunCode(
                () =>
                {
                    _remoteLocationRepository.Invoke(x => x.RemoveLocation(CurrentlySelectedLocation.Id));

                    _locations.Remove(CurrentlySelectedLocation);

                    CurrentlySelectedLocation = null;
                });
        }

        public void AddNewLocation()
        {
            var newWareWindowViewModel = new NewLocationViewModel(_remoteLocationRepository, _codeRunner);

            _applicationController.ShowNewLocationWindow(newWareWindowViewModel);

            if (newWareWindowViewModel.CreatedNewLocation)
            {
                LocationViewModel location = newWareWindowViewModel.GetNewlyCreatedLocation();

                _locations.Add(location);
            }
        }
    }
}